Přeskočit na hlavní obsah

Otázka č. 24 - Objektově orientované techniky

1. OOP

  • Objektově orientované programování (OOP) je paradigma programování, která se zaměřuje na práci s objekty.
  • Objekty jsou základními stavebními bloky v OOP a kombinují data (v podobě proměnných, nazývaných členy nebo atributy) a funkce (v podobě metod), které s těmito daty manipulují.
  • Hlavním cílem OOP je modelovat skutečný svět a usnadnit vývoj a údržbu softwarových aplikací tím, že umožní organizovat kód do srozumitelnějších a znovupoužitelných částí.

Základní principy

Dědičnost

  1. Třída (potomek), získává vlastnosti od svého rodiče (parent)
  2. Zděděné metody můžeme i přepisovat, a tak měnit i jejich funkčnost
  3. Každý potomek, může být i uložen v rozhraní rodiče
using System;
// Rodičovská třída
public class Vehicle
{
public void Drive()
{
Console.WriteLine("Vehicle is being driven.");
}
}
// Potomkovská třída, která dědí od Vehicle
public class Car : Vehicle
{
public void Accelerate()
{
Console.WriteLine("Car is accelerating.");
}
}
class Program
{
static void Main(string[] args)
{
Car myCar = new Car();
myCar.Drive(); // Metoda z dědičné třídy Vehicle
myCar.Accelerate(); // Metoda z potomkovské třídy Car
}
}

Zapouzdření

  1. minimalizace přímého přístupu k datům objektu
  2. přístup pouze prostřednictvím veřejných rozhraní (metod)
using System;
public class BankAccount
{
private decimal balance; // Privátní proměnná, k níž není přímý přístup zvenčí
public void Deposit(decimal amount)
{
balance += amount;
}
public void Withdraw(decimal amount)
{
if (amount <= balance)
{
balance -= amount;
}
else
{
Console.WriteLine("Insufficient funds!");
}
}
public decimal GetBalance()
{
return balance;
}
}
class Program
{
static void Main(string[] args)
{
BankAccount account = new BankAccount();
account.Deposit(1000);
account.Withdraw(500);
Console.WriteLine("Current balance: " + account.GetBalance());
}
}

Polymorfismus

  1. Polymorfismus umožňuje objektům stejného datového typu vykazovat různé chování na základě kontextu
  2. Statické - přetížení funkce
  3. Dynamické - Dědičnost a virtuální funkce
using System;
// Rodičovská třída s virtuální metodou
public class Shape
{
public virtual void Draw()
{
Console.WriteLine("Drawing a shape.");
}
}
// Potomkovská třída přepisuje virtuální metodu
public class Circle : Shape
{
public override void Draw()
{
Console.WriteLine("Drawing a circle.");
}
}
// Další potomkovská třída přepisuje virtuální metodu
public class Rectangle : Shape
{
public override void Draw()
{
Console.WriteLine("Drawing a rectangle.");
}
}
class Program
{
static void Main(string[] args)
{
Shape shape1 = new Circle(); // Dynamický polymorfismus
Shape shape2 = new Rectangle(); // Dynamický polymorfismus
shape1.Draw(); // Volá metodu Draw() definovanou pro Circle
shape2.Draw(); // Volá metodu Draw() definovanou pro Rectangle
}
}

2. Třídy a Objekty

Objekt

  • Obejkt je instance třídy
    • stav
    • chování
    • Identita
  • Konkrétní instance třídy
  • Příklad: Můžeme si představit třídu "Auto" a objekt "mé_auto", který je konkrétní instancí této třídy. Objekt "mé_auto" může mít atributy jako barvu, rychlost, značku atd. a metody jako "zapnout_motor()", "zastavit()" atd.

Atribut

  • Atribut je proměnná, která je součástí objektu a obsahuje data
  • Atributy definují vlastnosti objektu
  • Příklad: Pro objekt "mé_auto" mohou být atributy barva (např. "červená"), rychlost (např. "120 km/h"), značka (např. "Toyota") atd.

Metoda

  • Metoda je funkce, která je asociována s objektem a umožňuje provádět operace nad objektem nebo manipulovat s jeho atributy.
  • Metoda definuje chování objektu.
  • Příklad: Pro objekt "mé_auto" může být metoda "zrychlit()", která zvýší rychlost auta o určitou hodnotu.

Třída

  • Třída je šablona, podle které jsou vytvářeny objekty.
  • Definuje atributy (data) a metody (funkce), které budou mít objekty dané třídy
  • Příklad: Třída "Auto" může definovat atributy jako barva, rychlost, značka a metody jako "zapnout_motor()", "zastavit()" atd.

Instance třídy

  • Instance třídy je konkrétní objekt vytvořený podle definice třídy.
  • Každá instance třídy má svůj vlastní stav, ale sdílí stejné chování (metody) definované ve třídě.
  • Příklad: Objekt "mé_auto" je instancí třídy "Auto". Další instance třídy "Auto" může být například objekt "auto_kamaráda", který má své vlastní atributy a chování, ale je odvozený z téže třídy "Auto".
//příklad třídy
public class Auto
{
// Atributy třídy
public string Barva { get; set; }
public int Rychlost { get; set; }
public string Znacka { get; set; }
// Metoda pro zrychlení auta
public void Zrychlit(int hodnota)
{
Rychlost += hodnota;
Console.WriteLine($"Auto bylo zrychleno na {Rychlost} km/h.");
}
// Metoda pro zastavení auta
public void Zastavit()
{
Rychlost = 0;
Console.WriteLine("Auto bylo zastaveno.");
}
}

//příklad instance třídy
class Program
{
static void Main(string[] args)
{
// Vytvoření instance třídy Auto
Auto mojeAuto = new Auto();
mojeAuto.Barva = "červená";
mojeAuto.Rychlost = 60;
mojeAuto.Znacka = "Toyota";
// Použití metody pro zrychlení auta
mojeAuto.Zrychlit(20);
// Použití metody pro zastavení auta
mojeAuto.Zastavit();
// Vytvoření další instance třídy Auto
Auto autoKamarada = new Auto();
autoKamarada.Barva = "modrá";
autoKamarada.Rychlost = 80;
autoKamarada.Znacka = "BMW";
// Použití metody pro zrychlení auta
autoKamarada.Zrychlit(30);
}
}

3. Dědičnost

  • Dědičnost je koncept v objektově orientovaném programování, který umožňuje vytvářet nové třídy (tzv. podtřídy nebo odvozené třídy) na základě existujících tříd (tzv.nadřazené třídy nebo rodičovské třídy).
  • Tato nová třída zdědí vlastnosti (atributy a metody) nadřazené třídy a může přidávat další vlastní vlastnosti nebo metody anebo přepisovat existující chování.
  • Dědičnost umožňuje znovupoužití kódu, zjednodušuje hierarchii tříd a umožňuje efektivnější organizaci kódu.
// Nadřazená třída (rodičovská třída)
public class Vozidlo
{
public string Barva { get; set; }
public int Rychlost { get; set; }

public void Zrychlit(int hodnota)
{
Rychlost += hodnota;
Console.WriteLine($"Vozidlo bylo zrychleno na {Rychlost} km/h.");
}
public virtual void Zastavit() // Virtuální metoda, kterou může odvozená třída přepsat
{
Rychlost = 0;
Console.WriteLine("Vozidlo bylo zastaveno.");
}
}
// Odvozená třída (podtřída)
public class Auto : Vozidlo
{
public string Znacka { get; set; }

public void VypsatInformace()
{
Console.WriteLine($"Auto značky {Znacka} je {Barva} a jede {Rychlost} km/h.");
}
public override void Zastavit() // Přepsání metody Zastavit
{
base.Zastavit(); // Volání metody Zastavit z nadřazené třídy
Console.WriteLine("Auto bylo úspěšně zastaveno.");
}
}
class Program
{
static void Main(string[] args)
{
Auto auto = new Auto();
auto.Barva = "červená";
auto.Rychlost = 60;
auto.Znacka = "Toyota";
auto.VypsatInformace(); // Vypíše informace o autě
auto.Zrychlit(20); // Zrychlí auto
auto.Zastavit(); // Zastaví auto
}
}

4. Konstruktory

  • Konstruktory jsou speciální metody v třídách, které se používají k inicializaci nově vytvořené instance třídy. Konstruktor je volán při vytváření nové instance třídy pomocí klíčového slova new.

  • Vzájemné volání konstruktorů umožňuje jednomu konstruktoru třídy volat jiný konstruktor téže třídy, což usnadňuje sdílení kódu a zamezí opakování inicializačního kódu.

  • Předávání řízení mezi konstruktory se používá k inicializaci různých částí objektu z různých konstruktorů. To umožňuje flexibilní a čisté vytváření instancí tříd.

  • Volání konstruktoru rodičovské třídy se provádí pomocí klíčového slova base ve tvaru base(parametry). Tímto způsobem lze inicializovat členské proměnné a chování, které jsou definovány v rodičovské třídě.

public class Auto : Vozidlo
{
public string Znacka { get; set; }
// Konstruktor třídy Auto, který volá konstruktor rodičovské třídy
public Auto(string barva, int rychlost, string znacka) : base(barva, rychlost)
{
Znacka = znacka;
}
}
// Při volání konstruktoru rodičovské třídy pomocí base(parametry) můžeme předat parametry, které jsou potřeba pro inicializaci rodičovské třídy.

5. Abstraktní třída

  • Abstraktní třída je třída, která obsahuje alespoň jednu abstraktní metodu. Abstraktní metoda je metoda, která je deklarována, ale nemá implementaci. Abstraktní třídy nelze instanciovat, pouze dědit.
  • Používají se k definici obecných vlastností a chování, které jsou společné pro všechny třídy, které ji dědí. Každá dědící třída musí implementovat všechny abstraktní metody své abstraktní rodičovské třídy.
  • Abstraktní Metody deklarované bez implementace, které musí být implementovány v dědících třídách.
public abstract class Tvar
{
public abstract double Plocha();
public abstract double Obvod();
}
public class Kruh : Tvar
{
public double Polomer { get; set; }

public override double Plocha()
{
return Math.PI * Polomer * Polomer;
}
public override double Obvod()
{
return 2 * Math.PI * Polomer;
}
}

6. Rozhraní

  • Rozhraní definuje sadu abstraktních metod a vlastností, které třída musí implementovat. Jedná se o čistě abstraktní koncept, který specifikuje, co třída umí, ale neříká, jak to dělá.
  • Používá se k definici kontraktu mezi různými částmi kódu. Pomáhá oddělit rozhraní od implementace a umožňuje různým třídám implementovat stejnou funkcionalitu bez nutnosti dědění.
public interface IVozidlo
{
void Start();
void Zastavit();
}
public class Auto : IVozidlo
{
public void Start()
{
Console.WriteLine("Auto nastartováno.");
}
public void Zastavit()
{
Console.WriteLine("Auto zastaveno.");
}
}

7. Výčtový typ (ENUM)

  • Výčtový typ je speciální datový typ, který má pevně definovanou množinu konstantních hodnot. Tyto hodnoty jsou obvykle spojeny s čísly a nemohou být změněny během běhu programu.

  • Používá se k definici množiny hodnot, které mohou nabývat určitého typu, například dny v týdnu, směry, stavy atd.

public enum Smery
{
Vychod,
Zapad,
Sever,
Jih
}
Smery smer = Smery.Vychod;

8. Polyformismus

  • Polymorfismus je schopnost objektu reagovat na stejný způsob na různé typy zpráv nebo metody. To umožňuje používat jednu metodu nebo vlastnost s různými typy objektů.

  • Používá se k vytváření flexibilních a znovupoužitelných programů, kde stejná metoda může mít různé implementace pro různé typy objektů.

public class Postava
{
public virtual void Pozdrav()
{
Console.WriteLine("Ahoj, jsem postava.");
}
}
public class Hrdina : Postava
{
public override void Pozdrav()
{
Console.WriteLine("Ahoj, jsem hrdina.");
}
}
Postava postava = new Hrdina();
postava.Pozdrav(); // Vypíše: Ahoj, jsem hrdina.

9. Přetížení metod a funkcí

  • Přetížení metod nebo funkcí je možnost definovat více metod nebo funkcí stejného názvu v jedné třídě nebo oboru platnosti. Tyto metody musí mít různé počty nebo typy parametrů.
  • Přetížené metody se liší v počtu parametrů nebo jejich typech.
public class Kalkulacka
{
public int Secti(int a, int b)
{
return a + b;
}
public double Secti(double a, double b)
{
return a + b;
}
}

Kalkulacka kalkulacka = new Kalkulacka();
int vysledek1 = kalkulacka.Secti(3, 5); // Výsledek: 8
double vysledek2 = kalkulacka.Secti(3.5, 2.5); // Výsledek: 6.0

10. Modifikátory přístupu

  • jsou klíčová slova v jazyce C#, která určují, kdo může přistupovat k členům třídy (metodám, vlastnostem, polím) a z jakých částí kódu.

  • Modifikátory přístupu kontrolují viditelnost členů třídy z ostatních částí kódu.

  • Používají se k omezení přístupu k určitým částem kódu, což pomáhá zachovat bezpečnost, oddělení zodpovědností a udržitelnost kódu.

  1. Public - Člen je přístupný z libovolné části kódu.
  2. Private - Člen je přístupný pouze zevnitř třídy, ve které je definován.
  3. Protected - Člen je přístupný pouze zevnitř třídy a zevnitř odvozených tříd.
  4. Internal - Člen je přístupný pouze z částí kódu ve stejném projektu.
  5. Protected Internal - Člen je přístupný zevnitř třídy, zevnitř odvozených tříd a z částí kódu ve stejném projektu.

Anonymní metody a třídy

  • jsou konstrukce v jazyce C#, které umožňují vytvářet funkce a třídy bez explicitního deklarování jejich názvu.
  • Anonymní metoda je bez-jmenná metoda, která může být vytvořena přímo v místě jejího použití. Anonymní třída je třída bez názvu, která může být definována a vytvořena na místě.
  • Používají se k definici krátkých a jednoduchých funkcí nebo tříd přímo tam, kde jsou potřeba, což zjednodušuje syntaxi a činí kód čitelnějším a kompaktnějším.
public delegate void Del(string message);
class Program
{
static void Main(string[] args)
{
Del delegateInstance = delegate(string message)
{
Console.WriteLine(message);
};
delegateInstance("Toto je anonymní metoda.");
}
}

public interface IVozidlo
{
void Start();
}
class Program
{
static void Main(string[] args)
{
IVozidlo auto = new IVozidlo()
{
Start = () => Console.WriteLine("Startování vozidla.")
};
auto.Start();
}
}

12. Vyjímky

  • jsou situace v běhu programu, které narušují normální tok programu. Tyto situace mohou být způsobeny chybami v kódu, neočekávanými podmínkami nebo externími faktory. Mechanismus výjimek v jazyce C# umožňuje detekci, signalizaci a zpracování těchto neobvyklých situací.

Mechanismus předávání vyjímek

  • Pokud dojde k výjimečné situaci, metoda vytvoří objekt výjimky a přeruší běh programu.
  • Výjimka je předána volající metodě, která ji může zachytit a zpracovat, nebo je předána další vyšší úrovni kódu.
  • Pokud výjimka není zachycena, běh programu bude ukončen a na konzoli může být vypsána chybová zpráva.

Zpracování vyjímek

  • Výjimky jsou zpracovány pomocí bloku try-catch. Blok try obsahuje kód, který může vyvolat výjimku, a blok catch obsahuje kód, který zpracovává výjimku, pokud k ní dojde.
using System;
public class MojeException : Exception
{
public MojeException(string message) : base(message)
{
}
}
public class Program
{
public static void Main(string[] args)
{
try
{
throw new MojeException("Toto je moje vlastní výjimka.");
}
catch (MojeException ex)
{
Console.WriteLine("Zachycena vlastní výjimka: " + ex.Message);
}
}
}

13. Aktivní/pasivní ošetření chyb

  • Aktivní ošetření chyb zahrnuje mechanismy, které se snaží minimalizovat výskyt chyb při provádění operací. To zahrnuje kontrolu vstupních dat, ověřování podmínek a zabezpečení, aby nedošlo k neočekávaným situacím.

  • Pasivní ošetření chyb zahrnuje zachycení a zpracování chyb, které již nastaly. To zahrnuje použití bloků try-catch k zachycení výjimek a zpracování chybových stavů.

14. Návrhové vzory

  • jsou osvědčené postupy, které řeší běžné problémy v návrhu softwarových aplikací. Každý vzor je popisný šablonou, která popisuje problém, jeho řešení a důsledky jeho použití.

Singleton

  • návrhový vzor, který zajišťuje, že třída má pouze jednu instanci a poskytuje globální přístup k této instanci.
  • používá, když je třeba zajistit, že třída má pouze jednu instanci, například v případě správce konfigurace nebo připojení k databázi.

Factory method

  • návrhový vzor, který umožňuje definovat metodu pro vytváření objektů v nadřazené třídě a nechat podtřídy rozhodnout, který konkrétní objekt vytvoří.
  • Používá se, když třída nepředem nezná své konkrétní podtypy a chce, aby podtřídy rozhodly, jaké objekty vytvoří

Observer

  • Listener je návrhový vzor, který definuje závislost "jeden na mnoho" mezi objekty, takže když se změní stav jednoho objektu (subjektu), všechny závislé objekty (posluchači) jsou informovány a aktualizovány automaticky.
  • Používá se v situacích, kdy je třeba upozornit několik objektů na změny v jiném objektu, například v GUI aplikacích nebo u událostí.

Mediator

  • návrhový vzor, který definuje objekt (mediátor), který řídí komunikaci mezi dalšími objekty (kolegy). Objekty nekomunikují přímo mezi sebou, ale pouze přes mediátora.

  • Používá se v situacích, kdy je třeba oddělit různé části systému a snížit vzájemnou závislost, což zlepšuje modularitu a udržitelnost kódu.